#include <string>
#include <iostream>

class HasPtr
{
public:
    HasPtr(const std::string& ps);

    HasPtr(const HasPtr& ptr);

    HasPtr& operator=(const HasPtr& ptr);

    void print();

    ~HasPtr();

private:
    std::string* p;
    std::size_t* use;
    int i;
};

HasPtr::HasPtr(const std::string& ps) : p(new std::string(ps)), use(new std::size_t(1)), i(0) {};

HasPtr::HasPtr(const HasPtr& ptr): p(ptr.p), i(ptr.i), use(ptr.use) {++*use;};

HasPtr& HasPtr::operator=(const HasPtr& ptr)
{
    ++*ptr.use; // 递增右侧运算对象的引用计数
    if(--*use == 0) // 递减本对象的引用计数
    {
        delete p; // 如果没有其他用户
        delete use; // 释放本对象分配的内存
    }

    p = ptr.p; // 将数据从ptr拷贝到本对象
    i = ptr.i;
    use = ptr.use;

    return *this; // 返回本对象
}

void HasPtr::print()
{
    std::cout << *p << std::endl;
    std::cout << *use << std::endl;
}

HasPtr::~HasPtr()
{
    if(--*use == 0) // 如果引用计数变为0
    {
        delete p; // 释放string内存
        delete use; // 释放计数器内存
    }
}

int main()
{
    HasPtr test_ptr("hello");
    test_ptr.print();

    HasPtr test_ptr2 = test_ptr;
    test_ptr2.print();
    test_ptr.print();

    HasPtr test_ptr3("world");
    test_ptr3.print();

    test_ptr3 = test_ptr2;
    test_ptr3.print();
    test_ptr2.print();

    std::string* p1 = new std::string("hello");
    std::string* p2 = new std::string("world");
    std::swap(p1, p2);
    std::cout << *p1 << " " << *p2 << std::endl;

    return 0;
}